bitkeeper revision 1.100.1.1 (3e5d12a9XS1t15We3dHlj4sxiwEeWQ)
authorach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>
Wed, 26 Feb 2003 19:16:57 +0000 (19:16 +0000)
committerach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk>
Wed, 26 Feb 2003 19:16:57 +0000 (19:16 +0000)
add create segment code in xen,
/proc/xeno/dom0/vhd in xenolinux

14 files changed:
.rootkeys
BitKeeper/etc/logging_ok
xen/Makefile
xen/drivers/block/xen_block.c
xen/drivers/block/xen_segment.c [new file with mode: 0644]
xen/drivers/ide/ide-xeno.c
xen/include/hypervisor-ifs/block.h
xen/include/xeno/sched.h
xen/include/xeno/segment.h [new file with mode: 0644]
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c [new file with mode: 0644]
xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c

index 79b0d1d19730ec6989c066c057044e5cb3eb00b6..bd815702a8cfc2c0dac00c012d58d7af664f3075 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c
 3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
 3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
+3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
 3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
 3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c
 3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/xen_serial.c
 3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xeno/prefetch.h
 3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h
 3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h
+3e5d129a2bbGTpVSZFN_mAnbm97ixw xen/include/xeno/segment.h
 3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h
 3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h
 3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h
 3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
 3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
 3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
+3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
 3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/Makefile
 3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/console.c
 3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/Makefile
index f4f9934995125c8f00bc0df8b58992ed1174679d..cc166e63588c28ffe70c9a417d7bc1f5b02f5d44 100644 (file)
@@ -1,3 +1,4 @@
+ach61@labyrinth.cl.cam.ac.uk
 akw27@boulderdash.cl.cam.ac.uk
 akw27@labyrinth.cl.cam.ac.uk
 akw27@plucky.localdomain
index 3bd4299075b66d8746ac4dddda6b7518981c982d..85e451491939e43cb3c7e1ed2fdbed1f1acd90e0 100644 (file)
@@ -39,3 +39,5 @@ TAGS:
        find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
        find $(SUBDIRS) -name '*.[ch]' | xargs etags -a
 
+MAP:
+       nm image | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
index 805fd9e1ae75bb48365a934887a895ab9c7f4bf2..8e1ff1188b5b24ee394914e18a413b8b1ab08cb3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * xen-block.c
+ * xen_block.c
  *
  * process incoming block io requests from guestos's.
  */
@@ -16,6 +16,7 @@
 #include <asm/spinlock.h>
 #include <xeno/keyhandler.h>
 #include <xeno/interrupt.h>
+#include <xeno/segment.h>
 
 #if 0
 #define DPRINTK(_f, _a...) printk( _f , ## _a )
@@ -42,7 +43,10 @@ static int do_block_io_op_domain(struct task_struct *p, int max_to_do);
 static void dispatch_rw_block_io(struct task_struct *p, int index);
 static void dispatch_probe_block_io(struct task_struct *p, int index);
 static void dispatch_debug_block_io(struct task_struct *p, int index);
-static void make_response(struct task_struct *p, void *id, unsigned long st);
+static void dispatch_create_segment(struct task_struct *p, int index);
+static void dispatch_delete_segment(struct task_struct *p, int index);
+static void make_response(struct task_struct *p, void *id, int op, 
+                         unsigned long st);
 
 
 /******************************************************************
@@ -149,7 +153,8 @@ static void end_block_io_op(struct buffer_head *bh, int uptodate)
     }
 
     atomic_dec(&nr_pending);
-    make_response(bh->b_xen_domain, bh->b_xen_id, uptodate ? 0 : 1);
+    make_response(bh->b_xen_domain, bh->b_xen_id, 
+                 XEN_BLOCK_READ, uptodate ? 0 : 1);
 
     kmem_cache_free(buffer_head_cachep, bh);
 
@@ -205,6 +210,14 @@ static int do_block_io_op_domain(struct task_struct* p, int max_to_do)
            dispatch_debug_block_io(p, i);
            break;
 
+       case XEN_BLOCK_SEG_CREATE:
+           dispatch_create_segment(p, i);
+           break;
+
+       case XEN_BLOCK_SEG_DELETE:
+           dispatch_delete_segment(p, i);
+           break;
+
        default:
            panic("error: unknown block io operation [%d]\n",
                   blk_ring->ring[i].req.operation);
@@ -220,16 +233,43 @@ static void dispatch_debug_block_io(struct task_struct *p, int index)
     DPRINTK("dispatch_debug_block_io: unimplemented\n"); 
 }
 
+static void dispatch_create_segment(struct task_struct *p, int index)
+{
+  blk_ring_t *blk_ring = p->blk_ring_base;
+  xv_disk_t *xvd;
+  int result;
+
+  if (p->domain != 0)
+  {
+    printk (KERN_ALERT "dispatch_create_segment called by dom%d\n", p->domain);
+    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1); 
+    return;
+  }
+
+  xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);    
+  result = xen_segment_create(xvd);
+  make_response(p, blk_ring->ring[index].req.id, 
+               XEN_BLOCK_SEG_CREATE, result); 
+  return;
+}
+
+static void dispatch_delete_segment(struct task_struct *p, int index)
+{
+    DPRINTK("dispatch_delete_segment: unimplemented\n"); 
+}
+
 static void dispatch_probe_block_io(struct task_struct *p, int index)
 {
-    extern void ide_probe_devices(xen_disk_info_t *xdi);
+    extern void ide_probe_devices(xen_disk_info_t *xdi, int *count, 
+                                 drive_t xdrives[]);
     blk_ring_t *blk_ring = p->blk_ring_base;
     xen_disk_info_t *xdi;
 
     xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);    
-    ide_probe_devices(xdi);
+    ide_probe_devices(xdi, &num_xdrives, xdrives);
+    /* scsi_probe_devices(xdi, &num_xdrives, xdrives); */          /* future */
 
-    make_response(p, blk_ring->ring[index].req.id, 0);
+    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, 0);
 }
 
 static void dispatch_rw_block_io(struct task_struct *p, int index)
@@ -333,9 +373,9 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
     return;
 
  bad_descriptor:
-    make_response(p, blk_ring->ring[index].req.id, 1);
+    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_READ, 1);
     return;
-}
+} 
 
 
 
@@ -343,7 +383,8 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
  * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
  */
 
-static void make_response(struct task_struct *p, void *id, unsigned long st)
+static void make_response(struct task_struct *p, void *id, 
+                         int op, unsigned long st)
 {
     unsigned long cpu_mask, flags;
     int position;
@@ -353,8 +394,9 @@ static void make_response(struct task_struct *p, void *id, unsigned long st)
     spin_lock_irqsave(&p->blk_ring_lock, flags);
     blk_ring = p->blk_ring_base;
     position = blk_ring->resp_prod;
-    blk_ring->ring[position].resp.id     = id;
-    blk_ring->ring[position].resp.status = st;
+    blk_ring->ring[position].resp.id        = id;
+    blk_ring->ring[position].resp.operation = op;
+    blk_ring->ring[position].resp.status    = st;
     blk_ring->resp_prod = BLK_RING_INC(position);
     spin_unlock_irqrestore(&p->blk_ring_lock, flags);
     
@@ -377,6 +419,7 @@ void init_blkdev_info(struct task_struct *p)
     clear_page(p->blk_ring_base);
     SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p->domain);
     p->blkdev_list.next = NULL;
+    p->segment_count = 0;
 }
 
 /* End-of-day teardown for a domain. XXX Outstanding requests? */
@@ -397,6 +440,8 @@ void initialize_block_io ()
     buffer_head_cachep = kmem_cache_create(
         "buffer_head_cache", sizeof(struct buffer_head),
         0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+    xen_segment_initialize();
     
     add_key_handler('b', dump_blockq, "dump xen ide blkdev stats");     
 }
diff --git a/xen/drivers/block/xen_segment.c b/xen/drivers/block/xen_segment.c
new file mode 100644 (file)
index 0000000..1105afe
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * xen_segment.c
+ */
+
+#include <xeno/config.h>
+#include <xeno/types.h>
+#include <xeno/lib.h>
+#include <asm/io.h>
+#include <xeno/slab.h>
+#include <xeno/segment.h>
+#include <xeno/sched.h>
+#include <xeno/keyhandler.h>
+#include <hypervisor-ifs/block.h>
+
+int     num_xdrives;
+drive_t xdrives[XEN_MAX_DISK_COUNT];
+
+segment_t xsegments[XEN_MAX_SEGMENTS];
+
+/*
+ * xen_refresh_segment_list
+ *
+ * find all segments associated with a domain and assign
+ * them to the domain
+ */
+void xen_refresh_segment_list (struct task_struct *p)
+{
+  int loop;
+
+  for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
+  {
+    if (xsegments[loop].mode != XEN_SEGMENT_UNUSED &&
+       xsegments[loop].domain == p->domain)
+    {
+      p->segment_list[xsegments[loop].segment_number] = &xsegments[loop];
+      p->segment_count++;
+    }
+  }
+  return;
+}
+
+/*
+ * create a new segment for a domain
+ *
+ * return 0 on success, 1 on failure
+ *
+ * TODO: need to check to see if the DOM#/SEG# combination
+ *       already exists. if so, reuse the slot in the segment table.
+ */
+int xen_segment_create(xv_disk_t *xvd_in)
+{
+  int idx;
+  int loop;
+  xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
+
+  for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++)
+  {
+    if (xsegments[idx].mode == XEN_SEGMENT_UNUSED) break;
+  }
+  if (idx == XEN_MAX_SEGMENTS)
+  {
+    printk (KERN_ALERT "error: xen_segment_create unable to find free slot\n");
+    return 1;
+  }
+
+  xsegments[idx].mode = xvd->mode;
+  xsegments[idx].domain = xvd->domain;
+  xsegments[idx].segment_number = xvd->segment;
+  xsegments[idx].num_extents = xvd->ext_count;
+  xsegments[idx].extents = (extent_t *)kmalloc(sizeof(extent_t)*xvd->ext_count,
+                                              GFP_KERNEL);
+  /* could memcpy, but this is safer */
+  for (loop = 0; loop < xvd->ext_count; loop++)
+  {
+    xsegments[idx].extents[loop].disk = xvd->extents[loop].disk;
+    xsegments[idx].extents[loop].offset = xvd->extents[loop].offset;
+    xsegments[idx].extents[loop].size = xvd->extents[loop].size;
+  }
+
+  return 0;
+}
+
+/*
+ * delete a segment from a domain
+ *
+ * return 0 on success, 1 on failure
+ *
+ * TODO: caller must ensure that only domain 0 calls this function
+ */
+int xen_segment_delete(struct task_struct *p, xv_disk_t *xvd)
+{
+  return 0;
+}
+
+static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs) 
+{
+  int loop, i;
+
+  printk (KERN_ALERT "xdrives\n");
+  for (loop = 0; loop < num_xdrives; loop++)
+  {
+    printk (KERN_ALERT " %2d: major: 0x%d\n", loop, xdrives[loop].major);
+  }
+  
+  printk (KERN_ALERT "segments\n");
+  for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
+  {
+    if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
+    {
+      printk (KERN_ALERT " %2d: %s dom%d, seg# %d, num_exts: %d\n",
+             loop, 
+             xsegments[loop].mode == XEN_SEGMENT_RO ? "RO" : "RW",
+             xsegments[loop].domain, xsegments[loop].segment_number,
+             xsegments[loop].num_extents);
+      for (i = 0; i < xsegments[loop].num_extents; i++)
+      {
+       printk (KERN_ALERT "     ext %d: disk %d, offset 0x%lx, size 0x%lx\n",
+               i, xsegments[loop].extents[i].disk,
+               xsegments[loop].extents[i].offset,
+               xsegments[loop].extents[i].size);
+      } 
+    }
+  }
+}
+
+/*
+ * initialize segments
+ */
+
+void xen_segment_initialize(void)
+{
+  memset (xdrives, 0, sizeof(xdrives));
+  memset (xsegments, 0, sizeof(xsegments));
+
+  add_key_handler('S', dump_segments, "dump segments");
+}
index 0b7e481ddfaafcbb69dabd602d0e49c48bb40a5a..9da5a89b9ba0b4a89d2d6a2da2fe45a5fa27ae75 100644 (file)
@@ -2,11 +2,12 @@
 #include <xeno/types.h>
 #include <xeno/lib.h>
 #include <xeno/ide.h>
+#include <xeno/segment.h>
 #include <hypervisor-ifs/block.h>
 #include <asm/domain_page.h>
 #include <asm/io.h>
 
-void ide_probe_devices (xen_disk_info_t* xdi)
+void ide_probe_devices (xen_disk_info_t* xdi, int *count, drive_t xdrives[])
 {
     int loop;
     unsigned int unit;
@@ -21,21 +22,27 @@ void ide_probe_devices (xen_disk_info_t* xdi)
                unsigned long capacity;
                ide_drive_t *drive = &hwif->drives[unit];
 
-               if (drive->present) {
-                   capacity = current_capacity (drive);
+               /* only count drives with capacity > 0. this excludes cdroms */
+               if (drive->present && (capacity = current_capacity(drive)))
+               {
                    xen_xdi->disks[xen_xdi->count].type = XEN_DISK_IDE;
                    xen_xdi->disks[xen_xdi->count].capacity = capacity;
+                   xdrives[xen_xdi->count].major = hwif->major;
                    xen_xdi->count++;
 
+                   /*
                    printk (KERN_ALERT "IDE-XENO %d\n", xen_xdi->count);
                    printk (KERN_ALERT "  capacity 0x%lx\n", capacity);
                    printk (KERN_ALERT "  head     0x%x\n",  drive->bios_head);
                    printk (KERN_ALERT "  sector   0x%x\n",  drive->bios_sect);
                    printk (KERN_ALERT "  cylinder 0x%x\n",  drive->bios_cyl);
+                   printk (KERN_ALERT "  major    0x%x\n",  hwif->major);
+                   */
                }
            }
        }
     }
+    *count = xen_xdi->count;
 
     unmap_domain_mem(xen_xdi);
 }
index 627055bf0bf1e0359fa086be1a64474f9698a67c..908f8382cce61e7d5312e0ba07b80be6a09af8ff 100644 (file)
@@ -1,10 +1,7 @@
 /******************************************************************************
  * block.h
  *
- * Block IO communication rings.
- *
- * These are the ring data structures for buffering messages between 
- * the hypervisor and guestos's.  
+ * shared structures for block IO.
  *
  */
 
 
 #include <linux/kdev_t.h>
 
+/*
+ *
+ * These are the ring data structures for buffering messages between 
+ * the hypervisor and guestos's.  
+ *
+ */
+
 /* the first four definitions match fs.h */
 #define XEN_BLOCK_READ  0
 #define XEN_BLOCK_WRITE 1
@@ -20,6 +24,8 @@
 #define XEN_BLOCK_SPECIAL 4                              /* currently unused */
 #define XEN_BLOCK_PROBE 8      /* determine io configuration from hypervisor */
 #define XEN_BLOCK_DEBUG 16                                          /* debug */
+#define XEN_BLOCK_SEG_CREATE 32                      /* create segment (vhd) */
+#define XEN_BLOCK_SEG_DELETE 64                      /* delete segment (vhd) */
 
 #define BLK_RING_SIZE        128
 #define BLK_RING_MAX_ENTRIES (BLK_RING_SIZE - 2)
@@ -29,7 +35,7 @@
 typedef struct blk_ring_req_entry 
 {
     void *          id;                /* for guest os use */
-    int             operation;         /* XEN_BLOCK_READ or XEN_BLOCK_WRITE */
+    int             operation;         /* from above */
     char *          buffer;
     unsigned long   block_number;      /* block number */
     unsigned short  block_size;        /* block size */
@@ -39,8 +45,9 @@ typedef struct blk_ring_req_entry
 
 typedef struct blk_ring_resp_entry
 {
-    void *id;
-    unsigned long status;
+    void *          id;                                  /* for guest os use */
+    int             operation;                                 /* from above */
+    unsigned long   status;
 } blk_ring_resp_entry_t;
 
 typedef struct blk_ring_st 
@@ -53,7 +60,13 @@ typedef struct blk_ring_st
     } ring[BLK_RING_SIZE];
 } blk_ring_t;
 
-#define MAX_XEN_DISK_COUNT 100
+/*
+ *
+ * physical disk (xhd) info, used by XEN_BLOCK_PROBE
+ *
+ */
+
+#define XEN_MAX_DISK_COUNT 100
 
 #define XEN_DISK_IDE  1
 #define XEN_DISK_SCSI 2
@@ -71,8 +84,33 @@ typedef struct xen_disk                                     /* physical disk */
 
 typedef struct xen_disk_info
 {
-  int         count; /* number of subsequent xen_disk_t structures to follow */
-  xen_disk_t  disks[100];
+  int         count;            /* number of xen_disk_t structures to follow */
+  xen_disk_t  disks[XEN_MAX_DISK_COUNT];
 } xen_disk_info_t;
 
+/*
+ *
+ * virtual disk (vhd) structures, used by XEN_BLOCK_SEG_{CREATE, DELETE}
+ *
+ */
+
+#define XEN_DISK_READ_WRITE  1
+#define XEN_DISK_READ_ONLY   2
+
+typedef struct xv_extent
+{
+  int disk;                                          /* physical disk number */
+  unsigned long offset;               /* offset in blocks into physical disk */
+  unsigned long size;                                      /* size in blocks */
+} xv_extent_t;
+
+typedef struct xv_disk
+{
+  int mode;                     /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */
+  int domain;                                                      /* domain */
+  int segment;                                             /* segment number */
+  int ext_count;                          /* number of xv_extent_t to follow */
+  xv_extent_t extents[XEN_MAX_DISK_COUNT];    /* arbitrary reuse of constant */
+} xv_disk_t;
+
 #endif
index b0855f7b0ac828837343481851104aa826f02e42..0b7d96d790fbbb3c0f4adf90b95d0faa4885d062 100644 (file)
@@ -55,6 +55,7 @@ extern struct mm_struct init_mm;
 
 #include <xeno/vif.h>
 #include <xeno/block.h>
+#include <xeno/segment.h>
 
 struct task_struct {
 
@@ -79,6 +80,8 @@ struct task_struct {
     unsigned int blk_req_cons; /* request consumer */
     struct list_head blkdev_list;
     spinlock_t blk_ring_lock;
+    segment_t *segment_list[XEN_MAX_SEGMENTS];                        /* vhd */
+    int segment_count;
 
     int has_cpu, policy, counter;
 
diff --git a/xen/include/xeno/segment.h b/xen/include/xeno/segment.h
new file mode 100644 (file)
index 0000000..f0bf08f
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __SEGMENT_H__
+#define __SEGMENT_H__
+
+#include <hypervisor-ifs/block.h>
+
+void xen_segment_initialize(void);
+void xen_refresh_segment_list (struct task_struct *p);
+int xen_segment_create(xv_disk_t *xvd);
+
+#define XEN_MAX_SEGMENTS 100     /* total number of segments across all doms */
+
+/*
+ * every physical disk that xen has access to is listed in the drives array.
+ * we export the drive# to domain 0.  to xen, each drive is just one long
+ * array of blocks.
+ */
+
+typedef struct drive
+{
+  unsigned int major; 
+} drive_t;
+
+extern int     num_xdrives;
+extern drive_t xdrives[XEN_MAX_DISK_COUNT];
+
+/*
+ * virtual hard disks
+ *
+ * each segment is composed of a number of extents
+ */
+
+typedef struct extent
+{
+  int disk;            /* index into drives array of where this extent lives */
+  unsigned long offset;                                  /* offset into disk */
+  unsigned long size;                                 /* size of this extent */
+} extent_t;
+
+#define XEN_SEGMENT_UNUSED 0                                /* bzero default */
+#define XEN_SEGMENT_RO XEN_DISK_READ_WRITE
+#define XEN_SEGMENT_RW XEN_DISK_READ_ONLY
+
+typedef struct segment
+{
+  int mode;                                             /* UNUSED, RO, or RW */
+  int domain;
+  int segment_number;                           /* segment number for domain */
+  int num_extents;                                      /* number of extents */
+  extent_t *extents;
+} segment_t;
+
+#endif
index 74a0c6c5654d8d2e959337db3233b9c9326f4e55..c6d1c7dc6311ca770eddad4b148b31ef99b83d8f 100644 (file)
@@ -1,3 +1,3 @@
 O_TARGET := blk.o
-obj-y := xl_block.o xl_block_test.o
+obj-y := xl_block.o xl_segment.o xl_block_test.o
 include $(TOPDIR)/Rules.make
index 0b77e5536e6570dc1e7c31e3685812488804b526..6e7e713c866a0b34c28b8b553a1dfb868b2b438b 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/hypervisor-ifs/block.h>
 #include <asm/hypervisor-ifs/hypervisor-if.h>
 #include <asm/io.h>
+#include <asm/atomic.h>
 #include <asm/uaccess.h>
 
 #define MAJOR_NR XLBLK_MAJOR   /* force defns in blk.h, must precede include */
@@ -58,6 +59,7 @@ static int xlblk_max_sectors[XLBLK_MAX];
 static blk_ring_t *blk_ring;
 static unsigned int resp_cons; /* Response consumer for comms ring. */
 static xen_disk_info_t xen_disk_info;
+atomic_t xlblk_control_count;
 
 int hypervisor_request(void *         id,
                        int            operation,
@@ -166,7 +168,7 @@ static int xenolinux_block_revalidate(kdev_t dev)
  *   virtual address in the guest os.
  * block_number:  block to read
  * block_size:  size of each block
- * device:  ide/hda is 768 or 0x300
+ * device:  ide/hda is 768 or 0x300           should be disk#!!!
  */
 int hypervisor_request(void *         id,
                        int            operation,
@@ -193,6 +195,8 @@ int hypervisor_request(void *         id,
 
     switch ( operation )
     {
+    case XEN_BLOCK_SEG_CREATE:
+    case XEN_BLOCK_SEG_DELETE:
     case XEN_BLOCK_PROBE:
        phys_device = (kdev_t) 0;
        sector_number = 0;
@@ -321,7 +325,21 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
          i  = BLK_RING_INC(i) )
     {
        blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp;
-        if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1);
+       switch (bret->operation)
+       {
+         case XEN_BLOCK_READ :
+         case XEN_BLOCK_WRITE :
+           if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1);
+           break;
+           
+         case XEN_BLOCK_SEG_CREATE :
+         case XEN_BLOCK_SEG_DELETE :
+           atomic_dec(&xlblk_control_count);
+           break;
+         
+         default:
+           break;
+       }
     }
     
     resp_cons = i;
@@ -337,6 +355,8 @@ int __init xlblk_init(void)
 {
     int i, error, result;
 
+    atomic_set(&xlblk_control_count, 0);
+
     /* This mapping was created early at boot time. */
     blk_ring = (blk_ring_t *)fix_to_virt(FIX_BLKRING_BASE);
     blk_ring->req_prod = blk_ring->resp_prod = resp_cons = 0;
@@ -356,6 +376,7 @@ int __init xlblk_init(void)
         BUG();
     HYPERVISOR_block_io_op();
     while ( blk_ring->resp_prod != 1 ) barrier();
+    printk (KERN_ALERT "block device probe:\n");
     for ( i = 0; i < xen_disk_info.count; i++ )
     { 
        printk (KERN_ALERT "  %2d: type: %d, capacity: %ld\n",
index 2ddef271e562bf655c4b6dd36464466974931648..8d695689bab18242356c31e4b2a3be45faa0803c 100644 (file)
@@ -138,6 +138,11 @@ int proc_write_bdt(struct file *file, const char *buffer,
   sscanf(local, "%c %i %i %i", 
         &opcode, &block_number, &block_size, &device);
 
+  if (data)
+  {
+    kfree(data);
+  }
+
   if (opcode == 'r' || opcode == 'R')
   {
     meta.operation = XEN_BLOCK_READ;
@@ -151,6 +156,31 @@ int proc_write_bdt(struct file *file, const char *buffer,
     meta.operation = XEN_BLOCK_DEBUG;
     block_size = 10000;
   }
+  else if (opcode == 'c' || opcode == 'C')
+  {
+    xv_disk_t *xvd;
+    int loop;
+
+    meta.operation = XEN_BLOCK_SEG_CREATE;
+    data = kmalloc (sizeof(xv_disk_t), GFP_KERNEL);
+    if (data == NULL)
+    {
+      kfree(local);
+      return -ENOMEM;
+    }
+    
+    xvd = (xv_disk_t *)data;
+    xvd->mode = XEN_DISK_READ_WRITE;
+    xvd->domain = block_number;
+    xvd->segment = block_size;
+    xvd->ext_count = device;
+    for (loop = 0; loop < xvd->ext_count; loop++)
+    {
+      xvd->extents[loop].disk = block_number + 1;                  /* random */
+      xvd->extents[loop].offset = block_size + 1;
+      xvd->extents[loop].size = device + 1;
+    }
+  }
   else
   {
     printk(KERN_ALERT 
@@ -158,15 +188,14 @@ int proc_write_bdt(struct file *file, const char *buffer,
     return -EINVAL;
   }
 
-  if (data)
-  {
-    kfree(data);
-  }
-  data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
   if (data == NULL)
   {
-    kfree(local);
-    return -ENOMEM;
+    data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
+    if (data == NULL)
+    {
+      kfree(local);
+      return -ENOMEM;
+    }
   }
 
   meta.block_number = block_number;
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
new file mode 100644 (file)
index 0000000..da14be1
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * xl_segment.c
+ * 
+ * XenoLinux virtual disk driver.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+
+#include <asm/hypervisor-ifs/block.h>
+#include <asm/hypervisor-ifs/hypervisor-if.h>
+
+static struct proc_dir_entry *vhd;
+xv_disk_t xvd;
+
+extern atomic_t xlblk_control_count;                           /* xl_block.c */
+
+/******************************************************************/
+
+static int proc_read_vhd(char *page, char **start, off_t off,
+                        int count, int *eof, void *data)
+{
+  return 0;
+}
+
+#define isdelim(c) \
+  (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
+
+char *get_string(char *string)                          /* a bit like strtok */
+{
+  static char *temp;
+  int loop = 0;
+
+  if (string != NULL)  
+    temp = string;
+  else
+    string = temp;
+
+ try_again:
+
+  while (!isdelim(string[loop]))
+  {
+    if (string[loop] == '\0')
+      return NULL;
+    loop++;
+  }
+
+  string[loop] = '\0'; 
+  temp = (string + loop + 1);
+
+  if (loop == 0)
+  {
+    string = temp;
+    goto try_again;
+  }
+
+  return string;
+}
+
+
+#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
+unsigned long to_number(char *string)                                /* atoi */
+{
+  unsigned long value = 0;
+
+  if (string == NULL) return 0;
+
+  while (!isdigit(*string) && *string != '\0') string++;
+
+  while (isdigit(*string))
+  {
+    value = value * 10 + (*string - '0');
+    string++;
+  }
+
+  return value;
+}
+
+static int proc_write_vhd(struct file *file, const char *buffer,
+                         unsigned long count, void *data)
+{
+  char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
+  char *string;
+  int loop;
+  int counter;
+  xv_disk_t xvd;
+
+  memset (&xvd, 0, sizeof(xvd));
+
+  if (copy_from_user(local, buffer, count))
+  {
+    return -EFAULT;
+  }
+  local[count] = '\0';
+
+  string = get_string(local);                             /* look for Domain */
+  if (string == NULL)                                        /* empty string */
+  {
+    return count;
+  }
+  if (*string != 'd' && *string != 'D')
+  {
+    printk (KERN_ALERT 
+           "error: domain specifier missing [%s]. should be \"domain\".\n",
+           string);
+    return count;
+  }
+
+  string = get_string(NULL);                                /* domain number */
+  if (string == NULL)
+  {
+    printk (KERN_ALERT "error: domain number missing\n");
+    return count;
+  }
+  xvd.domain = (int) to_number(string);
+
+  string = get_string(NULL);
+  if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
+  {
+    xvd.mode = XEN_DISK_READ_ONLY;
+  }
+  else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
+  {
+    xvd.mode = XEN_DISK_READ_ONLY;
+  }
+  else
+  {
+    printk (KERN_ALERT 
+           "error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
+           string);
+    return count;
+  }
+
+  string = get_string(NULL);                             /* look for Segment */
+  if (string == NULL || (*string != 's' && *string != 'S'))
+  {
+    printk (KERN_ALERT 
+           "error: segment specifier missing [%s]. should be \"segment\".\n",
+           string);
+    return count;
+  }
+
+  string = get_string(NULL);                               /* segment number */
+  if (string == NULL)
+  {
+    printk (KERN_ALERT "error: segment number missing\n");
+    return count;
+  }
+  xvd.segment = (int) to_number(string);
+
+  string = get_string(NULL);                             /* look for Extents */
+  if (string == NULL || (*string != 'e' && *string != 'E'))
+  {
+    printk (KERN_ALERT 
+           "error: extents specifier missing [%s]. should be \"extents\".\n",
+           string);
+    return count;
+  }
+
+  string = get_string(NULL);                            /* number of extents */
+  if (string == NULL)
+  {
+    printk (KERN_ALERT "error: number of extents missing\n");
+    return count;
+  }
+  xvd.ext_count = (int) to_number(string);
+
+  /* ignore parenthesis */
+
+  for (loop = 0; loop < xvd.ext_count; loop++)
+  {
+    string = get_string(NULL);                              /* look for Disk */
+    if (string == NULL || (*string != 'd' && *string != 'D'))
+    {
+      printk (KERN_ALERT 
+             "hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
+             string);
+      return count;
+    }
+    string = get_string(NULL);                                /* disk number */
+    if (string == NULL)
+    {
+      printk (KERN_ALERT "error: disk number missing\n");
+      return count;
+    }
+    xvd.extents[loop].disk = (int) to_number(string);
+
+    string = get_string(NULL);                            /* look for Offset */
+    if (string == NULL || (*string != 'o' && *string != 'O'))
+    {
+      printk (KERN_ALERT 
+             "error: disk offset missing [%s]. should be \"offset\".\n",
+           string);
+      return count;
+    }
+    string = get_string(NULL);                                     /* offset */
+    if (string == NULL)
+    {
+      printk (KERN_ALERT "error: offset missing\n");
+      return count;
+    }
+    xvd.extents[loop].offset =  to_number(string);
+
+    string = get_string(NULL);                              /* look for Size */
+    if (string == NULL || (*string != 's' && *string != 'S'))
+    {
+      printk (KERN_ALERT 
+             "error: extent size missing [%s]. should be \"size\".\n",
+           string);
+      return count;
+    }
+    string = get_string(NULL);                                       /* size */
+    if (string == NULL)
+    {
+      printk (KERN_ALERT "error: extent size missing\n");
+      return count;
+    }
+    xvd.extents[loop].size =  to_number(string);
+  }
+
+  {
+    /* get lock xlblk_control_lock     */
+    counter = atomic_read(&xlblk_control_count);
+    atomic_inc(&xlblk_control_count);
+    /* release lock xlblk_control_lock */
+  }
+
+  hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
+                     0, 0, (kdev_t) 0);
+  HYPERVISOR_block_io_op();
+
+  while (atomic_read(&xlblk_control_count) != counter) barrier();
+
+  /* while ( blk_ring->resp_prod != 1 ) barrier(); */
+
+  /*  mdelay(1000); */
+
+  return count;
+}
+
+/******************************************************************/
+
+int __init xlseg_init(void)
+{
+  vhd = create_proc_entry("xeno/dom0/vhd", 0644, NULL);
+  if (vhd == NULL)
+  {
+    panic ("xlseg_init: unable to create vhd proc entry\n");
+  }
+  vhd->data       = NULL;
+  vhd->read_proc  = proc_read_vhd;
+  vhd->write_proc = proc_write_vhd;
+  vhd->owner      = THIS_MODULE;
+
+  memset(&xvd, 0, sizeof(xvd));
+
+  printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver installed\n");
+  return 0;
+}
+
+static void __exit xlseg_cleanup(void)
+{
+  printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver uninstalled\n");
+}
+
+#ifdef MODULE
+module_init(xlseg_init);
+module_exit(xlseg_cleanup);
+#endif
index 4fd98e94a5497a8d250190a9aaee2e155eb3a118..470b2067264112d7a92898ec063fd5f8721cd235 100644 (file)
@@ -1504,6 +1504,7 @@ int __init blk_dev_init(void)
 
 #ifdef CONFIG_XENOLINUX_BLOCK
     xlblk_init();
+    xlseg_init();
 #endif
 
        return 0;